package org.light.simpleauth;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.light.complexverb.ListMyActive;
import org.light.core.LayoutComb;
import org.light.core.ReportComb;
import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.ManyToMany;
import org.light.domain.Statement;
import org.light.domain.Util;
import org.light.exception.ValidateException;
import org.light.utils.DomainUtil;
import org.light.utils.WriteableUtil;
import org.light.verb.FindByName;

public class LoginServiceImplGenerator extends Util{
	protected Domain userDomain;
	protected Domain roleDomain;
	protected Domain privilegeDomain;
	protected List<Domain> domains;
	protected List<ManyToMany> mtms;
	protected List<LayoutComb> layouts;
	protected List<ReportComb> reports;
	
	public LoginServiceImplGenerator(){
		super();
		super.fileName = "LoginService.go";
	}

	@Override
	public String generateUtilString() throws ValidateException{
		List<Writeable> sList = new ArrayList<Writeable>();
		sList.add(new Statement(1000L,0,"package "+this.userDomain.getServiceimplSuffix()));
		sList.add(new Statement(2000L,0,""));

		sList.add(new Statement(3000L,0,"import ("));
		sList.add(new Statement(4000L,1,"\"strings\""));
		sList.add(new Statement(5000L,1,"\"regexp\""));
		sList.add(new Statement(6000L,1,"\"fmt\""));
		sList.add(new Statement(7000L,1,"collect \"github.com/chenhg5/collection\""));
		sList.add(new Statement(8000L,0,")"));
		sList.add(new Statement(9000L,0,""));
		sList.add(new Statement(10000L,0,"func CanAccess("+this.userDomain.findFieldByFixedName("userName").getLowerFirstFieldName()+" string, path string) bool{"));
		FindByName find = new FindByName(this.userDomain);
		sList.add(new Statement(11000L,1,this.userDomain.getLowerFirstDomainName()+" := "+find.getVerbName()+"("+this.userDomain.findFieldByFixedName("userName").getLowerFirstFieldName()+")"));
		ListMyActive lma = new ListMyActive(this.userDomain,this.roleDomain);
		sList.add(new Statement(12000L,1,"roles := "+lma.getVerbName()+"("+this.userDomain.getLowerFirstDomainName()+".Get"+this.userDomain.getDomainId().getCapFirstFieldName()+"());"));
		sList.add(new Statement(13000L,1,"roleNames := []string{}"));
		sList.add(new Statement(14000L,1,"permNames := []string{}"));
		sList.add(new Statement(15000L,1,"for _, role := range roles {"));
		sList.add(new Statement(16000L,2,"roleNames = append(roleNames, role.Get"+this.roleDomain.getDomainName().getCapFirstFieldName()+"())"));
		sList.add(new Statement(17000L,1,"}"));
		sList.add(new Statement(18000L,1,"for _, role := range roles {"));
		ListMyActive lmrpa = new ListMyActive(this.roleDomain,this.privilegeDomain);
		sList.add(new Statement(19000L,2,"perms := "+lmrpa.getVerbName()+"(role.Get"+this.roleDomain.getDomainId().getCapFirstFieldName()+"());"));
		sList.add(new Statement(20000L,2,"for _, perm := range perms {"));
		sList.add(new Statement(21000L,2,"permNames = append(permNames, perm.Get"+this.privilegeDomain.getDomainName().getCapFirstFieldName()+"())"));
		sList.add(new Statement(22000L,2,"}"));
		sList.add(new Statement(23000L,1,"}"));
		sList.add(new Statement(24000L,1,""));
		sList.add(new Statement(25000L,1,"fmt.Println(\"JerryDebug:roleNames:\",roleNames,\":\",permNames)"));
		sList.add(new Statement(26000L,1,"if collect.Collect(roleNames).Contains(\"admin\") {"));
		sList.add(new Statement(27000L,2,"return true"));
		sList.add(new Statement(28000L,1,"} else {"));
		sList.add(new Statement(29000L,2,"fmt.Println(\"JerryDebug:permNames:\",permNames)"));
		sList.add(new Statement(30000L,2,"return PermsCanAccess(permNames,path)"));
		sList.add(new Statement(31000L,1,"}"));
		sList.add(new Statement(32000L,0,"}"));
		sList.add(new Statement(33000L,0,""));
		sList.add(new Statement(34000L,0,"func PermsCanAccess(perms [] string, path string) bool{"));
		sList.add(new Statement(35000L,1,"pathPerms :=  GetPermsByPath(path)"));
		sList.add(new Statement(36000L,1,"fmt.Println(\"JerryDebug:pathPerms:\",pathPerms,\":\",path)"));
		sList.add(new Statement(37000L,0,""));
		sList.add(new Statement(38000L,1,"if collect.Collect(pathPerms).Contains(\"annon\") || collect.Collect(pathPerms).Contains(\"authc\"){"));
		sList.add(new Statement(39000L,3,"return true"));
		sList.add(new Statement(40000L,2,"}"));
		sList.add(new Statement(41000L,1,"fmt.Println(\"JerryDebug:cperms:\",pathPerms,\":\",perms)"));
		sList.add(new Statement(42000L,1,"for _, pathperm := range pathPerms {"));
		sList.add(new Statement(43000L,2,"if collect.Collect(pathPerms).Contains(\"noauth\") {"));
		sList.add(new Statement(44000L,3,"return false"));
		sList.add(new Statement(45000L,2,"} else 	if !collect.Collect(perms).Contains(pathperm) {"));
		sList.add(new Statement(46000L,3,"return false"));
		sList.add(new Statement(47000L,2,"}"));
		sList.add(new Statement(48000L,1,"}"));
		sList.add(new Statement(49000L,1,"return true"));
		sList.add(new Statement(50000L,0,"}"));
		sList.add(new Statement(51000L,0,""));
		sList.add(new Statement(52000L,0,"func GetPermsByPath(path string) [] string{"));
		sList.add(new Statement(53000L,1,"if strings.Compare(path, \"/\") == 0{"));
		sList.add(new Statement(54000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(55000L,1,"}"));
		
		sList.add(new Statement(55100L,1,"if strings.Compare(path, \"/favicon.ico\") == 0{"));
		sList.add(new Statement(55200L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(55300L,1,"}"));
		sList.add(new Statement(55400L,1,"if strings.Compare(path, \"/pages/\") == 0{"));
		sList.add(new Statement(55500L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(55600L,1,"}"));
		
		sList.add(new Statement(56000L,1,"if strings.Compare(path, \"/index.html\") == 0{"));
		sList.add(new Statement(57000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(58000L,1,"}"));
		sList.add(new Statement(59000L,0,""));
		sList.add(new Statement(60000L,1,"if strings.HasPrefix(path, \"/images/\"){"));
		sList.add(new Statement(61000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(62000L,1,"}"));
		sList.add(new Statement(63000L,1,"if strings.HasPrefix(path, \"/js/\") {"));
		sList.add(new Statement(64000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(65000L,1,"}"));
		sList.add(new Statement(66000L,1,"if strings.HasPrefix(path, \"/easyui/\") {"));
		sList.add(new Statement(67000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(68000L,1,"}"));
		sList.add(new Statement(69000L,1,"if strings.HasPrefix(path, \"/echarts/\"){"));
		sList.add(new Statement(70000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(71000L,1,"}"));
		sList.add(new Statement(72000L,1,"if strings.HasPrefix(path, \"/uploadjs/\"){"));
		sList.add(new Statement(73000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(74000L,1,"}"));
		sList.add(new Statement(75000L,1,"if strings.Compare(path, \"/login/index.html\") == 0 {"));
		sList.add(new Statement(76000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(77000L,1,"}"));
		sList.add(new Statement(78000L,1,"if strings.Compare(path, \"/login/register.html\") == 0 {"));
		sList.add(new Statement(79000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(80000L,1,"}"));
		sList.add(new Statement(81000L,1,"if  strings.Compare(path, \"/login/error.html\") == 0 {"));
		sList.add(new Statement(82000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(83000L,1,"}"));
		sList.add(new Statement(84000L,1,"if  strings.Compare(path, \"/login/noauth.html\") == 0 {"));
		sList.add(new Statement(85000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(86000L,1,"}"));
		
		sList.add(new Statement(86100L,1,"if  strings.Compare(path, \"/pages/index.html\") == 0 {"));
		sList.add(new Statement(86200L,2,"return  []string{\"authc\"}"));
		sList.add(new Statement(86300L,1,"}"));
		
		sList.add(new Statement(87000L,1,"if strings.HasPrefix(path, \"/login"+this.userDomain.getControllerNamingSuffix()+"/\") {"));
		sList.add(new Statement(88000L,2,"return  []string{\"annon\"}"));
		sList.add(new Statement(89000L,1,"}"));
		
		sList.add(new Statement(89100L,1,"if strings.HasPrefix(path, \"/profile"+this.userDomain.getControllerNamingSuffix()+"/\") {"));
		sList.add(new Statement(89200L,2,"return  []string{\"authc\"}"));
		sList.add(new Statement(89300L,1,"}"));
		
		sList.add(new Statement(89400L,1,"if strings.Compare(path, \"/pages/profile.html\") == 0 {"));
		sList.add(new Statement(89500L,2,"return  []string{\"authc\"}"));
		sList.add(new Statement(89600L,1,"}"));
		
		sList.add(new Statement(90000L,1,"pattern := `/*"+this.userDomain.getControllerNamingSuffix()+"/find*`"));
		sList.add(new Statement(91000L,1,"re := regexp.MustCompile(pattern)"));
		sList.add(new Statement(92000L,1,"if re.MatchString(path){"));
		sList.add(new Statement(93000L,2,"return  []string{\"authc\"}"));
		sList.add(new Statement(94000L,1,"}"));
		sList.add(new Statement(95000L,1,"pattern2 := `/*"+this.userDomain.getControllerNamingSuffix()+"/listActive*`"));
		sList.add(new Statement(96000L,1,"re2 := regexp.MustCompile(pattern2)"));
		sList.add(new Statement(97000L,1,"if re2.MatchString(path) {"));
		sList.add(new Statement(98000L,2,"return  []string{\"authc\"}"));
		sList.add(new Statement(99000L,1,"}"));
		sList.add(new Statement(100000L,1,"pattern3 := `/*"+this.userDomain.getControllerNamingSuffix()+"/listAll*`"));
		sList.add(new Statement(101000L,1,"re3 := regexp.MustCompile(pattern3)"));
		sList.add(new Statement(102000L,1,"if re3.MatchString(path) {"));
		sList.add(new Statement(103000L,2,"return  []string{\"authc\"}"));
		sList.add(new Statement(104000L,1,"}"));
		sList.add(new Statement(105000L,1,""));
		
		long serial = 110000L;
		Set<Domain> adminDomains = new TreeSet<>();
		adminDomains.add(this.getUserDomain());
		adminDomains.add(this.getRoleDomain());
		adminDomains.add(this.getPrivilegeDomain());
		if (this.getDomains()!=null&&this.getDomains().size()>0) {
			Set<Domain> myDomains = new TreeSet<>();
			myDomains.addAll(this.getDomains());
			for (Domain d:myDomains) {
				if (!DomainUtil.inDomainSet(d,adminDomains)) {
					sList.add(new Statement(serial,1,"if strings.Compare(path, \"/pages/"+d.getPlural().toLowerCase()+".html\") == 0 {"));
					sList.add(new Statement(serial+1000L,2,"return  []string{\""+d.getStandardName()+"\"}"));
					sList.add(new Statement(serial+2000L,1,"}"));
					sList.add(new Statement(serial+3000L,1,"if strings.HasPrefix(path, \"/"+d.getLowerFirstDomainName()+d.getControllerNamingSuffix()+"/\") {"));
					sList.add(new Statement(serial+4000L,2,"return  []string{\""+d.getStandardName()+"\"}"));
					sList.add(new Statement(serial+5000L,1,"}"));
					sList.add(new Statement(serial+6000L,1,""));
					serial += 7000L;
				}
			}
		}
		
		if (this.getMtms()!=null&&this.getMtms().size()>0) {
			for (ManyToMany mtm:this.getMtms()) {
				if (!DomainUtil.inDomainSet(mtm.getMaster(), adminDomains)) {
					sList.add(new Statement(serial,1,"if strings.Compare(path, \"/pages/"+mtm.getStandardName().toLowerCase()+".html\") == 0 {"));
					sList.add(new Statement(serial+1000L,2,"return  []string{\""+mtm.getMaster().getStandardName()+"\"}"));
					sList.add(new Statement(serial+2000L,1,"}"));
				}
				serial += 3000L;
			}
		}
		if (this.getLayouts()!=null&&this.getLayouts().size()>0) {
			for (LayoutComb lc:this.getLayouts()) {
				Set<Domain> mydomains = lc.getDomains();
				mydomains.removeAll(adminDomains);
				sList.add(new Statement(serial,1,"if strings.Compare(path, \"/pages/"+lc.getStandardName().toLowerCase()+".html\") == 0 {"));
				sList.add(new Statement(serial+1000L,2,"return  []string{"+DomainUtil.DomainSetNamesWithQuote(mydomains)+"}"));
				sList.add(new Statement(serial+2000L,1,"}"));
				sList.add(new Statement(serial+3000L,1,""));
				serial += 4000L;
			}
		}
		if (this.getReports()!=null&&this.getReports().size()>0) {
			for (ReportComb rc:this.getReports()) {
				Set<Domain> mydomains = rc.getDomains();
				mydomains.removeAll(adminDomains);
				sList.add(new Statement(serial,1,"if strings.Compare(path, \"/pages/"+rc.getStandardName().toLowerCase()+".html\") == 0 {"));
				sList.add(new Statement(serial+1000L,2,"return  []string{"+DomainUtil.DomainSetNamesWithQuote(mydomains)+"}"));
				sList.add(new Statement(serial+2000L,1,"}"));
				sList.add(new Statement(serial+3000L,1,""));
				serial += 4000L;
			}
		}

		sList.add(new Statement(serial+19000L,1,"return  []string{\"noauth\"}"));
		sList.add(new Statement(serial+20000L,0,"}"));

		return WriteableUtil.merge(sList).getContent();		
	}

	public Domain getUserDomain() {
		return userDomain;
	}

	public void setUserDomain(Domain userDomain) {
		this.userDomain = userDomain;
		if ("datadummy".equalsIgnoreCase(this.userDomain.getSchema())) {
			super.fileName = "LoginDummyService.go";	
		}
	}

	public Domain getRoleDomain() {
		return roleDomain;
	}

	public void setRoleDomain(Domain roleDomain) {
		this.roleDomain = roleDomain;
	}

	public Domain getPrivilegeDomain() {
		return privilegeDomain;
	}

	public void setPrivilegeDomain(Domain privilegeDomain) {
		this.privilegeDomain = privilegeDomain;
	}

	public List<Domain> getDomains() {
		return domains;
	}

	public void setDomains(List<Domain> domains) {
		this.domains = domains;
	}

	public List<ManyToMany> getMtms() {
		return mtms;
	}

	public void setMtms(List<ManyToMany> mtms) {
		this.mtms = mtms;
	}

	public List<LayoutComb> getLayouts() {
		return layouts;
	}

	public void setLayouts(List<LayoutComb> layouts) {
		this.layouts = layouts;
	}

	public List<ReportComb> getReports() {
		return reports;
	}

	public void setReports(List<ReportComb> reports) {
		this.reports = reports;
	}

}
